mod testmod;

use rand::Rng;
use std::{cmp::Ordering, io};

fn main() {
    // println!("Hello, world!");
    // let a = 0;      // a不可变变量
    // let mut b = 1;  // b可变变量
    // const MAX_NUM: u32 = 1_000_000;

    testmod::a();
    // let x = 5;
    // let y = {
    //     let x = 3;
    //     // x+1是返回值(表达式), 加分号就成了语句
    //     x + 1
    // };
    // println!("The value of x is: {}", x);
    // println!("The value of y is: {}", y);

    const TEST: u32 = 2_147_483_647;
    println!("{}", TEST);

    let index = 8;
    if index == 0 {
        guess_game_fn();
    } else if index == 1 {
        arr_fn(-1, index);
    } else if index == 2 {
        println!("The value of five fun is: {}", plus_one(five()));
    } else if index == 3 {
        if_fn();
    } else if index == 4 {
        loop_fn();
    } else if index == 5 {
        for_fn();
    } else if index == 6 {
        tup_fn();
    } else if index == 7 {
        string_fn();
    } else if index == 8 {
        slice_fn();
    } else {
    }
}

fn guess_game_fn() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);
    loop {
        println!("Please input your guess.");

        let mut guess = String::new();

        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");

        // let guess: u32 = guess.trim().parse().expect("Please type a number!");
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => {
                println!("Please type a number!");
                continue;
            }
        };
        println!("You guessed: {}", guess);

        // 类型 switch 结构
        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }
}

fn five() -> i32 {
    if false {
        return -5;
    }
    5
}

fn plus_one(x: i32) -> i32 {
    x + 1
}

fn if_fn() {
    let a = if true { 1 } else { 0 };
    println!("{}", a);
}

fn loop_fn() {
    let mut counter = 0;
    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;
        }
    };

    println!("{}", result);
    assert_eq!(result, 20);
}

fn for_fn() {
    let a: [i32; 5] = [1, 2, 3, 4, 5];
    println!("the value is: {}", a[0]);

    let a = [10, 20, 30, 40, 50];

    for element in a.iter() {
        println!("the value is: {}", element);
    }
}

fn arr_fn(print_num: i32, index: usize) {
    println!("{}", print_num);
    let months = ["January", "Feburray"];
    println!("{}", months[index]);
}

fn tup_fn() {
    let tup = (500, 6.4, 1);
    let (x, y, z) = tup;
    println!("{}  {}  {}", x, y, z);
    println!("{}  {}  {}", tup.0, tup.1, tup.2);
}

fn string_fn() {
    // 栈里的已知长度
    // let a = "hi"; //定长字符串， 在程序中
    // let b = a;
    // println!("{} {}", a, b);

    // 堆内存里的字符串， 不定长度

    // let mut s = String::from("hello");
    // s.push_str(", world!");
    // println!("{}", s);

    // let s1 = String::from("hello");
    // let s2 = s1; //堆内存一个字符串， s1被移动到s2
    // let s3 = s2.clone(); //堆内存两个字符串，s3是s2的克隆
    // println!("{} {}, world!", s2, s3);

    let str1 = String::from("hello");
    let str2 = refence_fn(str1); //值传递， 所有权转移到str2（移动）
    println!("{}, world!", str2);
    println!("str len is {}", str_len_fn(&str2)); //引用传递， 所有权不变
    let mut str3 = str2; //移动~
    append_str(&mut str3); //可变引用传递， 所有权不变
    println!("{}", str3);
}

fn append_str(s: &mut String) {
    s.push_str("ss");
}
fn str_len_fn(s: &String) -> usize {
    s.len()
}
fn refence_fn(s: String) -> String {
    s
}

fn slice_fn() {
    let s = String::from("hello world");
    let slice = &s[..];
    let hello = first_word(slice);
    println!("{}", hello);
}
fn first_word(s: &str) -> &str {
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..]
}
